//
// Created by 78472 on 2022/11/17.
//

#include <thread>
#include <unistd.h>
#include <atomic>
#include <cstdio>
#include <functional>

#include "qlibc/QData.h"
#include "param.h"
#include "log/Logging.h"
#include "common/httpUtil.h"
#include "service/serviceRequestHandler.h"
#include "siteService/nlohmann/json.hpp"
#include "siteService/service_site_manager.h"
#include "siteManage/siteManageUtil.h"

using namespace std;
using namespace httplib;
using json = nlohmann::json;
using namespace servicesite;


int main(int argc, char* argv[]){
    //增加log打印
    string path = "/data/changhong/edge_midware/lhy/querySiteLog.txt";
    muduo::logInitLogger(path);

    LOG_RED << "-----------------------------------------";
    LOG_RED << "-----------------------------------------";
    LOG_RED << "---------------QUERY_SITE START----------";
    LOG_RED << "-----------------------------------------";
    LOG_RED << "-----------------------------------------";

    ServiceSiteManager* serviceSiteManager = ServiceSiteManager::getInstance(); // 创建 serviceSiteManager 对象, 单例
    serviceSiteManager->setServerPort(QuerySitePort);
    serviceSiteManager->setSiteIdSummary(QuerySiteID, QuerySiteName);
    SiteTree::getInstance()->init();     //获取单例对象
    uploadLog::getInstance();
    httplib::ThreadPool threadPool_(20);

    //站点注册服务
    serviceSiteManager->registerServiceRequestHandler(Site_Register_Service_ID,
                                                      [](const Request& request, Response& response) -> int{
        return site_register_service_handler(request, response);
    });

    //站点注销服务
    serviceSiteManager->registerServiceRequestHandler(Site_UnRegister_Service_ID,
                                                      [](const Request& request, Response& response) -> int{
        return site_unRegister_service_handler(request, response);
    });

    //站点查询服务
    serviceSiteManager->registerServiceRequestHandler(Site_Query_Service_ID,
                                                      [&threadPool_](const Request& request, Response& response) -> int{
        return site_query_service_handler(request, response, threadPool_);
    });

    //站点心跳服务
    serviceSiteManager->registerServiceRequestHandler(Site_Ping_Service_ID,
                                                      [](const Request& request, Response& response) -> int{
        return site_ping_service_handler(request, response);
    });

    //获取本地站点信息
    serviceSiteManager->registerServiceRequestHandler(Site_LocalSite_Service_ID,
                                                      [](const Request& request, Response& response) -> int{
        return site_getLocalSiteInfo_service_handler(request, response);
    });

    //注册本站点发布的消息
    serviceSiteManager->registerMessageId(Site_OnOffLine_MessageID);        //上下线消息
    serviceSiteManager->registerMessageId(Site_RegisterAgain_MessageID);    //重新注册消息
    serviceSiteManager->registerMessageId(Site_Requery_Result_MessageID);   //站点查询结果消息  

    //注册消息处理函数
    serviceSiteManager->registerMessageHandler(ReportLog_MessageID, "mqtt_service", uploadLogHandler);      //上报日志
    serviceSiteManager->registerMessageHandler(Site_List_Update_MessageID, "master_coordinate", masterMessageHandle);   //主从站点app列表变更

    //订阅上报日志消息
    threadPool_.enqueue([&](){
        while(true){
            bool findMqtt{false};
            //从主从站点获取站点列表
            qlibc::QData request, response;
            request.setString("service_id", "get_app_site_list");
            request.putData("request", qlibc::QData());
            LOG_GREEN << "get_app_site_list request: " << request.toJsonString();
            if(httpUtil::sitePostRequest("127.0.0.1", 9012, request, response)){    //获取局域网内所有发现的站点
                LOG_BLUE << "get_app_site_list response: " << response.toJsonString();
                qlibc::QData app_site_list = response.getData("response").getData("app_site_list");
                Json::ArrayIndex size = app_site_list.size();
                for(Json::ArrayIndex i = 0; i < size; ++i){
                    qlibc::QData ithData = app_site_list.getArrayElement(i);
                    string site_id = ithData.getString("site_id");
                    string run_state = ithData.getString("run_state");
                    if(site_id == "mqtt_service" && run_state == "RUN_OK"){
                        string ip = ithData.getString("ip");
                        std::vector<string> mqttMessageIdList;
                        mqttMessageIdList.push_back(ReportLog_MessageID);   
                        int code = serviceSiteManager->subscribeMessage(ip, 9020, "mqtt_service", mqttMessageIdList);
                        if (code == ServiceSiteManager::RET_CODE_OK) {
                            LOG_PURPLE << "subscribeMessage reportLog ok....";
                            findMqtt = true;
                        }
                    }
                }
                if(findMqtt){
                    return;
                }
            }
            std::this_thread::sleep_for(std::chrono::seconds(10));
            LOG_RED << "subscribeMessage reportLog failed....., start to subscribe in 10 seconds";
        }
    });

     //订阅主从站点面板列表变更、应用站点列表变更
    threadPool_.enqueue([&](){
        while(true){
            std::vector<string> messageIdList;
            messageIdList.push_back(Site_List_Update_MessageID);
            //获取雷达站点ip
            int code = serviceSiteManager->subscribeMessage("127.0.0.1", 9012, "master_coordinate", messageIdList);
            if (code == ServiceSiteManager::RET_CODE_OK) {
                LOG_PURPLE << "subscribeMessage app_site_list_update ok....";
                return;
            }
            std::this_thread::sleep_for(std::chrono::seconds(10));
            LOG_RED << "subscribeMessage app_site_list_update failed....., start to subscribe in 5 seconds";
        }
    });


    // 站点监听线程启动
    threadPool_.enqueue([&](){
        while(true){
            //自启动方式
            int code = serviceSiteManager->start();
            if(code != 0){
                std::cout << "===>querySite startByRegister error, code = " << code << std::endl;
                std::cout << "===>querySite startByRegister in 3 seconds...." << std::endl;
                std::this_thread::sleep_for(std::chrono::seconds(3));
            }else{
                std::cout << "===>querySite startByRegister successfully....." << std::endl;
                break;
            }
        }
    });

    std::this_thread::sleep_for(std::chrono::seconds(1));
    //重新启动后，发布注册消息，使各个站点重新进行注册
    qlibc::QData registerAgain;
    registerAgain.setString("message_id", Site_RegisterAgain_MessageID);
    registerAgain.putData("content", qlibc::QData(Json::Value(Json::objectValue)));
    serviceSiteManager->publishMessage(Site_RegisterAgain_MessageID, registerAgain.toJsonString());
    LOG_PURPLE << "Notify all other sites to register again ...";

    while(true){
        std::this_thread::sleep_for(std::chrono::seconds(60 *10));
    }

    return 0;
}